package com.lb.util;



import com.lb.config.RedissonConfig;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.StringCodec;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;

/**
 * Redisson 分布式锁工具类（支持 Redis Cluster 模式）
 */
@Component
public class RedissonDistributedLockUtil {
    @Autowired
    private RedissonClient redissonClient1; // 实例字段

    private static RedissonClient redissonClient; // 静态字段

    /**
     * 在 Bean 初始化后，将实例字段赋值给静态字段
     */
    @PostConstruct
    public void init() {
        redissonClient = this.redissonClient1;
        System.out.println("✅ RedissonClient 已注入到静态工具类");
    }
  //  @Autowired
  //  private static RedissonClient redissonClient;

    // 容器注入后才能使用，不能用 static 初始化
   // private static RedissonClient redissonClient;

    // 初始化 Redisson 客户端（集群模式）
 //   static {
 //       Config config = new Config();
 //       config.useClusterServers()
 //               .setPassword("yourpassword") // 替换为你的密码
 //               .addNodeAddress(
 //                       "redis://47.120.36.156:30001",
 //                       "redis://47.120.36.156:30002",
 //                       "redis://47.120.36.156:30003",
 //                       "redis://47.120.36.156:30004",
 //                       "redis://47.120.36.156:30005",
 //                       "redis://47.120.36.156:30006"
 //               );
//
 //       redissonClient = org.redisson.Redisson.create(config);
 //   }

    /**
     * 获取分布式锁（支持重试机制）
     *
     * @param lockName        锁的名称
     * @param expireSeconds   锁自动过期时间（秒），防止死锁
     * @param maxRetries      最大重试次数（-1 表示无限重试）
     * @param retryIntervalMs 重试间隔时间（毫秒）
     * @return RLock 返回锁对象，需手动释放
     * @throws IllegalStateException 获取锁失败（仅当重试次数用尽）
     */
    public static RLock lock(String lockName, int expireSeconds, int maxRetries, long retryIntervalMs) {
        RLock lock = redissonClient.getLock(lockName);
        int attempt = 0;

        while (maxRetries < 0 || attempt <= maxRetries) {
            try {
                // 尝试加锁，设置锁过期时间，避免业务异常导致锁不释放
                boolean isLocked = lock.tryLock(retryIntervalMs, expireSeconds, TimeUnit.SECONDS);

                if (isLocked) {
                    System.out.println("✅ [" + Thread.currentThread().getName() +
                            "] 成功获取锁: " + lockName);
                    return lock;
                } else {
                    if (attempt == 0) {
                        System.out.println("🔒 锁被占用: " + lockName + "，准备重试...");
                    }
                    attempt++;
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("获取锁过程中线程被中断", e);
            } catch (Exception e) {
                System.err.println("⚠️ 获取锁异常: " + e.getMessage());
                try {
                    Thread.sleep(Math.min(1000, retryIntervalMs)); // 防止异常时高频重试
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException("异常重试时被中断", ie);
                }
            }
        }

        throw new IllegalStateException("❌ 获取锁失败，已达到最大重试次数: " + maxRetries);
    }

    public static String generateId(String bizPrefix, String region) {
        String date = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
        String key = "{id_seq}:" + bizPrefix + ":" + region + ":" + date;

        RAtomicLong counter = redissonClient.getAtomicLong(key);
        Long seq = counter.incrementAndGet(); // ✅ 这个方法不会爆红！

        if (seq == 1) {
            long seconds = getSecondsUntilTomorrow();
            counter.expire(seconds, TimeUnit.SECONDS);
        }

        String seqStr = String.format("%06d", seq % 1000000);
        return bizPrefix + date + region + seqStr;
    }

    /**
     * 计算距离明天凌晨的秒数
     */
    private static long getSecondsUntilTomorrow() {
        return LocalDate.now().plusDays(1).atStartOfDay().until(
                java.time.LocalDateTime.now().plusDays(1),
                java.time.temporal.ChronoUnit.SECONDS
        );
    }


    /**
     * 释放锁（安全释放，无需担心误删）
     *
     * @param lock RLock 对象
     */
    public static void unlock(RLock lock) {
        if (lock != null && lock.isHeldByCurrentThread()) {
            lock.unlock();
            System.out.println("🔓 [" + Thread.currentThread().getName() + "] 锁已释放");
        } else {
            System.out.println("⚠️ [WARN] 锁已被释放或不属于当前线程");
        }
    }

    /**
     * 获取 RedissonClient（可用于其他高级操作）
     */
    public static RedissonClient getClient() {
        return redissonClient;
    }

    /**
     * 关闭 Redisson 客户端（应用关闭时调用）
     */
    public static void shutdown() {
        if (redissonClient != null && !redissonClient.isShutdown()) {
            redissonClient.shutdown();
            System.out.println("👋 Redisson 客户端已关闭");
        }
    }
}